/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ttfsclient;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import myutil.Protocol;
import myutil.Utility;
import pojo.POJODownload;
import pojo.POJOFileUpload;
import pojo.POJOInfoClient;
import pojo.POJOProcess;

/**
 *
 * @author Tidus Le
 */
public class clsThreadDownload extends Thread
{
    POJODownload downFile;
    String cid;
    int delay;

    public clsThreadDownload(String cid, POJODownload downFile,int delay) {
        this.cid=cid;
        this.downFile = downFile;
        this.delay=delay;
        this.setName(downFile.getFid());
    }
    
    @Override
    public void run()
    {
        try
        {
            sleep(delay*1000);
            //Tính số lượng package
            float pk=(float)downFile.getFsize()/frmMain.maxData;
            int soPackage=(int)pk;
            if(pk>soPackage)
                soPackage++;
            
            //Lấy địa chỉ IP mới nhất của client cần down
            POJOInfoClient ic=clsRequestSV.getLocation(frmMain.myInfo, cid);
            
            //Kiem tra xem folder temp có tồn tại hay chưa
            File tempDir=new File(frmMain.tempDir+downFile.getFid());
            if(!tempDir.exists())
            {
                tempDir.mkdir();
            }
            
            
            //Bắt đầu xử lý download
            while(true)
            {
                boolean loop=false;
                //Kiểm tra xem file này còn ở chế độ download nữa hay không
                for(POJODownload down:frmMain.arrDownload)
                    if(down.getFid().equals(downFile.getFid())==true)
                        if(down.getStatus().equals("download")==true)
                        {
                            loop=true;
                            break;
                        }
                if(loop==false)
                    break;
                
                //Kiểm tra số lượng package đã download
                File[] listFile=tempDir.listFiles();
                ArrayList<Integer> arrFinish=new ArrayList<Integer>();
                for(File f:listFile)
                {
                    String fname=f.getName();
                    int number=Integer.parseInt(fname.substring(fname.lastIndexOf(".")+1, fname.length()));
                    arrFinish.add(number);
                }
                
                //Gửi thông tin yêu cầu danh sách các package
                Protocol prot=new Protocol();
                prot.setRp(true);
                prot.setFid(downFile.getFid());
                //Thong tin list package
                boolean full=true;
                ArrayList<Integer> listPackage=new ArrayList<Integer>();
                //Gửi yêu cầu send package
                try
                {
                    Socket sock=new Socket(ic.getIp(), Integer.parseInt(ic.getPort()));
                
                    //send request
                    OutputStream outStr=sock.getOutputStream();
                    ObjectOutputStream objOutStr=new ObjectOutputStream(outStr);
                    objOutStr.writeObject(prot);
                    objOutStr.flush();

                    //receive response
                    InputStream inStr=sock.getInputStream();
                    ObjectInputStream objInStr=new ObjectInputStream(inStr);
                    prot=(Protocol)objInStr.readObject();

                    if(prot.isFp()==false)
                    {
                        full=false;
                        if(prot.getId().isEmpty()==false)
                        {
                            String[] list=prot.getId().split(",");
                            for(String s:list)
                            {
                                try
                                {
                                    listPackage.add(Integer.parseInt(s));
                                }catch(Exception exx)
                                {
                                    System.out.println(exx.getMessage());
                                }
                            }
                        }
                    }

                    //close
                    objInStr.close();
                    objOutStr.close();
                    inStr.close();
                    outStr.close();
                    sock.close();
                }catch(Exception ex)
                {
                    System.out.println("Download connection lost: "+this.getName());
                    break;
                }
                
                ////////////////////////////////////
                //Tìm packge nào chưa down/////////
                int pkDownload=-1;
                for(int i=1;i<=soPackage;i++)
                {
                    boolean flag=false;
                    for(int c:arrFinish)
                        if(c==i)
                        {
                            flag=true;
                            break;
                        }
                    if(flag==false)
                        for(POJOProcess pro:frmMain.arrProcess)
                            if((pro.getFid().equals(downFile.getFid())==true)&&(pro.getStt()==i))
                            {
                                flag=true;
                                break;
                            }
                    if(flag==false)
                        if(full==false)
                        {
                            //Giả sử là không có package nào
                            flag=true;
                            for(int p:listPackage)
                                if(p==i)
                                {
                                    //Bên gửi có package này
                                    flag=false;
                                    break;
                                }
                        }
                    
                    if(flag==false)
                    {
                        POJOProcess pro=new POJOProcess();
                        pro.setFid(downFile.getFid());
                        pro.setStt(i);
                        pro.setThreadName(this.getName());
                        frmMain.arrProcess.add(pro);
                        pkDownload=i;
                        break;
                    }
                }
                if(pkDownload==-1)
                    break;
                
                //////////////////////////////////////////
                //Gửi thông tin yêu cầu send package//////
                prot=new Protocol();
                prot.setSp(true);
                prot.setFid(downFile.getFid());
                prot.setStt(pkDownload);
                //Gửi yêu cầu send package
                try
                {
                    Socket sock=new Socket(ic.getIp(), Integer.parseInt(ic.getPort()));
                
                    //send request
                    OutputStream outStr=sock.getOutputStream();
                    ObjectOutputStream objOutStr=new ObjectOutputStream(outStr);
                    objOutStr.writeObject(prot);
                    objOutStr.flush();

                    //receive response
                    InputStream inStr=sock.getInputStream();
                    ObjectInputStream objInStr=new ObjectInputStream(inStr);
                    prot=(Protocol)objInStr.readObject();

                    if(prot.isOff()==false)
                    {
                        FileOutputStream fOutStr=new FileOutputStream(tempDir.getAbsolutePath()+"\\"+downFile.getFname()+"."+pkDownload);
                        BufferedOutputStream buffOutStr=new BufferedOutputStream(fOutStr);

                        buffOutStr.write(prot.getData(),0,(int)prot.getLen());
                        buffOutStr.flush();

                        buffOutStr.close();
                        fOutStr.close();
                    }

                    //close
                    objInStr.close();
                    objOutStr.close();
                    inStr.close();
                    outStr.close();
                    sock.close();
                }catch(Exception ex)
                {
                    System.out.println("Download connection lost: "+this.getName());
                    break;
                }
            }
            
            //xóa pack trong mảng arrProcess
            int c=0;
            while(c<frmMain.arrProcess.size())
            {
                if(frmMain.arrProcess.get(c).getThreadName().equals(this.getName())==true)
                    frmMain.arrProcess.remove(c);
                else
                    c++;
            }
            
            //Kiểm tra xem có đủ số lượng package hay chưa
            boolean full=false;
            long currSize=Utility.sizeOfFolder(tempDir);
            if(currSize==downFile.getFsize())
                full=true;
            
            //Nếu mà đã lấy đủ số lượng các package
            if(full==true)
            {
                for(POJODownload down:frmMain.arrDownload)
                    if(down.getFid().equals(downFile.getFid())==true)
                        if(down.getStatus().equals("finish")==true)
                            return;
                        else
                        {
                            //Set trang thái
                            down.setStatus("finish");
                            
                            //Chuyển qua bên đã download
                            frmMain.arrDownloadComplete.add(down);
                            
                            //Set percent to 100%
                            frmMain.fidPer="full";
                            
                            //Xóa bên đang download
                            frmMain.arrDownload.remove(down);
                            
                            //Add thêm vô danh sách chia sẻ file
                            clsRequestSV.shareFile(down.getFid(), down.getFname(), down.getFsize(),frmMain.myInfo);

                            //lưu thông tin lại
                            boolean exist=false;
                            for(POJOFileUpload fuload:frmMain.arrFileUpload)
                                if(fuload.getFid().equals(down.getFid())==true)
                                {
                                    exist=true;
                                    break;
                                }

                            if(exist==false)
                            {
                                POJOFileUpload fu=new POJOFileUpload();
                                fu.setFid(down.getFid());
                                fu.setPath(down.getFpath());
                                frmMain.arrFileUpload.add(fu);
                            }
                            
                            //notify cho form main biết
                            frmMain.changeDownload=true;
                            frmMain.changeFileUpload=true;
                            
                            break;
                        }
                
                //Ghép file
                FileOutputStream fOutStr=new FileOutputStream(downFile.getFpath());
                BufferedOutputStream buffOutStr=new BufferedOutputStream(fOutStr);
                File[] listFile=tempDir.listFiles();
                for(c=1;c<=soPackage;c++)
                {
                    String p="";
                    for(File f:listFile)
                    {
                        String fname=f.getName();
                        try
                        {
                            int number=Integer.parseInt(fname.substring(fname.lastIndexOf(".")+1, fname.length()));
                            if(number==c)
                            {
                                p=f.getAbsolutePath();
                                break;
                            }
                        }catch(Exception ex)
                        {
                            System.out.println(ex.getMessage());
                        }
                    }


                    File file=new File(p);
                    FileInputStream fInStr=new FileInputStream(file);
                    int contentLength=(int)file.length();
                    byte[] content=new byte[contentLength];

                    BufferedInputStream buffInStr=new BufferedInputStream(fInStr);
                    buffInStr.read(content);
                    buffOutStr.write(content); //ghi
                    fInStr.close();
                    buffInStr.close();
                }

                buffOutStr.flush();

                buffOutStr.close();
                fOutStr.close();
                
                //Xoa tempDir
                Utility.deleteDir(tempDir);
            }
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
    }
}
